﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ParticularLocal
{
    public class SharedLocal
    {
        static dynamic Local;
        static ThreadLocal<string> ThreadLocal = new ThreadLocal<string>(() => "Initial Value");
        static AsyncLocal<string> AsyncLocal = new AsyncLocal<string> { Value = "Initial Value" };


        public async Task BendItWithYourMind()
        {
            // Assign the AsyncLocal to the dynamic field
            Local = AsyncLocal;

            // This code is the same as before but shown again for clarity
            Console.WriteLine($"Before TopOne: '{Local.Value}'");
            await TopOne().ConfigureAwait(false);
            Console.WriteLine($"After TopOne: '{Local.Value}'");
            await TopTen().ConfigureAwait(false);
            Console.WriteLine($"After TopTen: '{Local.Value}'");
        }

        public async Task ThereIsNoSpoon()
        {
            // Assign the ThreadLocal to the dynamic field
            Local = ThreadLocal;

            Console.WriteLine($"Before TopOne: '{Local.Value}'");
            await TopOne().ConfigureAwait(false);
            Console.WriteLine($"After TopOne: '{Local.Value}'");
            await TopTen().ConfigureAwait(false);
            Console.WriteLine($"After TopTen: '{Local.Value}'");
        }

        static async Task TopOne()
        {
            await Task.Delay(10).ConfigureAwait(false);
            Local.Value = "ValueSetBy TopOne";
            await Somewhere().ConfigureAwait(false);
        }

        static async Task TopTen()
        {
            await Task.Delay(10).ConfigureAwait(false);
            Local.Value = "ValueSetBy TopTen";
            await Somewhere().ConfigureAwait(false);
        }

        static async Task Somewhere()
        {
            await Task.Delay(10).ConfigureAwait(false);
            Console.WriteLine($"Inside Somewhere: '{Local.Value}'");
            await Task.Delay(10).ConfigureAwait(false);
            await DeepDown();
        }

        static async Task DeepDown()
        {
            await Task.Delay(10).ConfigureAwait(false);
            Console.WriteLine($"Inside DeepDown: '{Local.Value}'");
            await Fire();
        }

        static async Task Fire()
        {
            await Task.Yield();
            Console.WriteLine($"Inside Fire: '{Local.Value}'");
        }

    }

}
